/*
 * ThreadMediaReader.h
 *
 *  Created on: 2016��8��13��
 *      Author: zhengboyuan
 */

#ifndef THREADMEDIAREADER_H_
#define THREADMEDIAREADER_H_

#include "MediaReader.h"
#include "MediaSourceFactory.h"
#include "SharedPtr.h"
#include "FileMediaSink.h"
#include "MediaObject.h"
#include "CommandThread.h"
#include "TimePoint.h"
#include "PacketQueue.h"
#include "TimestampChecker.h"
#include "MediaSourceFramer.h"
#include "H264PropDetector.h"


namespace av
{


class ThreadMediaReader: public MediaReader, public util::CommandThread
{
public:
	static int STACK_SIZE;
    static int STREAM_BREAK_TIMEOUT;
    static size_t MAX_QUEUE_SIZE;

public:
	ThreadMediaReader();
	virtual ~ThreadMediaReader();

	virtual int open(const std::string& url, const std::string& params);

	virtual void close();

	virtual bool isOpen();

	virtual int getFormat(MediaFormat& fmt);

	virtual int getDuration();

	virtual int play();
	virtual int pause();
	virtual void stop();

	virtual int getState();

	virtual bool seekable();

	virtual int seek(int64_t offset);

	virtual int64_t getTime();

	virtual int setScale(float scale);

	virtual float getScale();

	virtual int read(AVPacketPtr& pkt);

	virtual void interrupt();

	virtual bool isLive();


	virtual int startRecord(const std::string& filename);
	virtual void stopRecord();
	virtual bool isRecording();

	virtual void setEventCallback(ReaderEventCallback cb, void* context);

	virtual void setHandle(int handle);

	virtual bool waitForReadable(int ms);

	virtual int step();
	virtual int nextKeyFrame();

	virtual int backward(int64_t offset);

	virtual int forward();

protected:
	enum PlayerCommandType
	{
		kOpen = 1,
		kClose,
		kPlay,
		kPause,
		kStop,
		kSeek,
		kFlush,

		kSetScale,
		kStep,
		kNextKeyFrame,
		kBackward,
		kForward,

		kSetProp,

		kSnap,
		kStartRecord,
		kStopRecord,

		kStartRender,
		kStopRender,
		kSetVideoWindow
	};

	void handleOpen();
	void handleClose();
	void handlePlay();
	void handlePause();
	void handleStop();
	void handleSeek(int64_t offset);
	void handleSetScale(AVRational scale);
	void handleStep();
	void handleNextKeyFrame();
	void handleBackward(int64_t offset);
	void handleForward();

	void handleSnap(const std::string& filePath);
	void handleFlush();
	void handleStartRecord(const std::string& filePath);
	void handleStopRecord();
	void handleSetProp(std::string& key, std::string& value);

	void handleStartRender();
	void handleStopRender();
	void handleSetVideoWindow(void* window);


	void fireMediaEvent(int type, int64_t value);
	void fireMediaPacket(AVPacketPtr& pkt);
	void fireMediaFormat(const MediaFormat& fmt);

	void doCloseFile();

	void setState(StreamState state);

	void dispatchPacket(AVPacketPtr& pkt);
	int computeDelay(AVPacketPtr& pkt);

	int64_t getClock();

	void delay(int ms);

	void resetTimePoint();

	bool readUntilVideoFrame();
	bool readUntilVideoKeyFrame();

	bool isFormatReady();
	void tryDispatchPacket(AVPacketPtr& pkt);

    void checkStreamBreak();

protected:
	virtual void onCommand(Command& cmd);
	virtual void onIdle();
	virtual bool startup();
	virtual void cleanup();
    virtual void doStop();

protected:
	std::string	m_url;
	std::string	m_params;

	MediaSourcePtr	m_source;
	MediaSourceFactoryPtr	m_factory;
	FileMediaSinkPtr	m_fileSink;

	MediaFormat	m_format;
	bool	m_isLive;

	TimePoint	m_startPoint;
	TimePoint	m_lastPoint;
	int		m_refStreamIndex;

	StreamState	m_state;

	int64_t			m_curTime;
	AVRational	    m_scale;
	comn::CriticalSection	m_cs;

	PacketQueue	m_pktQueue;

	bool	m_endOfStream;

	ReaderEventCallback	m_eventCallback;
	void*	m_eventContext;

	int		m_handle;

	util::TimestampChecker	m_tsChecker;

	std::shared_ptr< MediaSourceFramer >	m_sourceFramer;
	H264PropDetector	m_h26xPropDetector;

    int64_t m_streamActiveTime;
    bool m_streamOpened;
    int64_t m_checkstreamBreakTime;

};



} /* namespace av */

#endif /* THREADMEDIAREADER_H_ */
